/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.topisv.tms.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.taobao.api.internal.util.StringUtils;
import com.topisv.tms.rest.qimen.request.RequestParams;
import com.topisv.tms.rest.qimen.request.parse.RequestParamsParse;

/**
 *
 * @author Administrator
 */
public class TopUtils {
	protected static Logger log = LoggerFactory.getLogger(TopUtils.class);
	/**
	 * 给奇门的请求参数签名
	 * @param requestParam
	 * @return
	 * @throws Exception 
	 */
	public static String signQMRequest(RequestParams requestParam) throws Exception {
		// 第一步：检查参数是否已经排序
		String[] keys = requestParam.getParams().keySet().toArray(new String[0]);
		Arrays.sort(keys);
		String secret = requestParam.getSecret();
		boolean isHmac = "hmac".equals(requestParam.getParams().get(RequestParamsParse.SIGN_METHOD));
		// 第二步：把所有参数名和参数值串在一起
		StringBuilder query = new StringBuilder();
		if (!isHmac) {
			query.append(secret);
		}
		for (String key : keys) {
			if (RequestParamsParse.SIGN.equals(key)) {
                continue;
			}
			String value = requestParam.getParams().get(key);
			if (StringUtils.areNotEmpty(key, value)) {
				query.append(key).append(value);
			}
		}

		// 第三步：使用MD5/HMAC加密
		byte[] bytes;
		if (isHmac) {
			bytes = TopUtils.encryptHMAC(query.toString(), secret);
		} else {
			query.append(requestParam.getRequestXml());
			query.append(secret);
			bytes = TopUtils.encryptMD5(query.toString());
		}
		// 第四步：把二进制转化为大写的十六进制
		return TopUtils.byte2hex(bytes);
	}
	
    /**
	 * 给TOP请求签名。
	 * 
	 * @param requestHolder 所有字符型的TOP请求参数
	 * @param secret 签名密钥
	 * @param isHmac 是否为HMAC方式加密
	 * @return 签名
	 * @throws IOException
	 */
	public static String signTopRequestNew(Map<String, String> params, String secret, boolean isHmac) throws IOException {
		// 第一步：检查参数是否已经排序
		String[] keys = params.keySet().toArray(new String[0]);
		Arrays.sort(keys, String.CASE_INSENSITIVE_ORDER);

		// 第二步：把所有参数名和参数值串在一起
		StringBuilder query = new StringBuilder();
		if (!isHmac) {
			query.append(secret);
		}
		for (String key : keys) {
			String value = params.get(key);
			if (StringUtils.areNotEmpty(key, value)) {
				query.append(key).append(value);
			}
		}

		// 第三步：使用MD5/HMAC加密
		byte[] bytes;
		if (isHmac) {
			bytes = encryptHMAC(query.toString(), secret);
		} else {
			//query.append(secret);
			bytes = encryptMD5(query.toString());
		}

		// 第四步：把二进制转化为大写的十六进制
		return byte2hex(bytes);
	}
        
	public static byte[] encryptHMAC(String data, String secret) throws IOException {
		byte[] bytes = null;
		try {
			SecretKey secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacMD5");
			Mac mac = Mac.getInstance(secretKey.getAlgorithm());
			mac.init(secretKey);
			bytes = mac.doFinal(data.getBytes("UTF-8"));
		} catch (GeneralSecurityException gse) {
			String msg=getStringFromException(gse);
			throw new IOException(msg);
		}
		return bytes;
	}

	public static String getStringFromException(Throwable e) {
		String result = "";
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(bos);
		e.printStackTrace(ps);
		try {
			result = bos.toString("UTF-8");
		} catch (IOException ioe) {
		}
		return result;
	}

	public static byte[] encryptMD5(String data) throws IOException {
		byte[] bytes = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			bytes = md.digest(data.getBytes("UTF-8"));
		} catch (GeneralSecurityException gse) {
			String msg = getStringFromException(gse);
			log.error(msg);
			throw new IOException(msg);
		}
		return bytes;
	}

	public static String byte2hex(byte[] bytes) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		int j = bytes.length;
		char str[] = new char[j * 2];
		int k = 0;
		for (byte byte0 : bytes) {
			str[k++] = hexDigits[byte0 >>> 4 & 0xf];
			str[k++] = hexDigits[byte0 & 0xf];
		}
		return new String(str);
	}

	/**
	 * 清除字典中值为空的项。
	 * 
	 * @param <V> 泛型
	 * @param map 待清除的字典
	 * @return 清除后的字典
	 */
	public static <V> Map<String, V> cleanupMap(Map<String, V> map) {
		if (map == null || map.isEmpty()) {
			return null;
		}

		Map<String, V> result = new HashMap<String, V>(map.size());
		Set<Entry<String, V>> entries = map.entrySet();

		for (Entry<String, V> entry : entries) {
			if (entry.getValue() != null) {
				result.put(entry.getKey(), entry.getValue());
			}
		}

		return result;
	}
	/**
	 * 清除字典中值为空的项。
	 * 
	 * @param <V> 泛型
	 * @param map 待清除的字典
	 * @return 清除后的字典
	 */
	public static  Map<String, Object> cleanupMap2(Map<String, Object> map) {
		if (map == null) {
			return new HashMap<String, Object>();
		}
		
		Map<String, Object> result = new HashMap<String, Object>(map.size());
		Set<Entry<String, Object>> entries = map.entrySet();
		
		for (Entry<String, Object> entry : entries) {
			if (entry.getValue() != null && !StringUtils.isEmpty(entry.getValue().toString())) {
				result.put(entry.getKey(), entry.getValue());
			}
		}
		
		return result;
	}
}
